<?php

namespace App\HttpController\Api;

use App\HttpController\BaseController;
use App\HttpController\ResponseCode;
use App\Traits\LogTrait;
use App\Traits\RedisTrait;
use App\Traits\ResponseTrait;
use EasySwoole\Component\Context\ContextManager;
use EasySwoole\EasySwoole\Core;
use EasySwoole\EasySwoole\Trigger;
use EasySwoole\Http\Message\Status;
use EasySwoole\HttpAnnotation\Exception\Annotation\ParamValidateError;
use EasySwoole\ORM\DbManager;

// api 基础控制器定义
abstract class ApiBase extends BaseController
{
    use RedisTrait;
    use ResponseTrait;
    use LogTrait;

    public function index()
    {
        $this->actionNotFound('index');
    }

    protected function actionNotFound(?string $action): void
    {
        $this->failNotFound($action . '动作找不到');
    }

    public function onRequest(?string $action): ?bool
    {
        // 保存请求对象，以便后面可以使用
        ContextManager::getInstance()->set('request', $this->request());
        // 解决easyswoole不能解析application/json格式的post提交
        if (strpos($this->request()->getHeader('content-type')[0], 'application/json;charset=UTF-8') !== false) { //根据内容类型来转换参数
            $json = $this->json() ?: [];
            $this->request()->withParsedBody($json);
        }

        // 分页参数
        $page = $this->request()->getRequestParam('page');
        $limit = $this->request()->getRequestParam('limit');
        defined('PAGE') or define('PAGE', $page ?? 1);
        defined('PERPAGE') or define('PERPAGE', $limit ?? 20);

        // 每次请求到来都会执行的方法
        $this->init();

        if (!parent::onRequest($action)) {
            return false;
        };

        return true;
    }

    /**
     * 这个方法是用来解决控制器对象池复用模式问题的
     * @author LZH
     */
    protected function init(): void
    {
    }

    /**
     * 拦截异常
     * @param \Throwable $throwable
     */
    protected function onException(\Throwable $throwable): void
    {
        if ($throwable instanceof ParamValidateError) { // 参数验证异常
            $msg = $throwable->getValidate()->getError()->getErrorRuleMsg();
            $this->failValidationErrors($msg);
        } elseif ($throwable instanceof \EasySwoole\Jwt\Exception) { // token异常
            if ($throwable->getCode() == -2) {
                $this->failUnauthorized('token过期');
            }
        } else {
            if (Core::getInstance()->runMode() == 'dev') {
                $msg = $throwable->getFile(). ':' .$throwable->getLine().':'.$throwable->getMessage();
                $this->failServerError($msg);
                Trigger::getInstance()->throwable($throwable);
            } else {
                //拦截错误进日志,使控制器继续运行
                Trigger::getInstance()->throwable($throwable);
                $this->failServerError('系统内部错误，请稍后重试');
            }
        }
    }

    /**
     * 是否POST请求
     * @return bool
     */
    protected function isPost()
    {
        $method = $this->request()->getMethod();
        if ($method != 'POST') {
            return false;
        }
        return true;
    }

    /**
     * 是否GET请求
     * @return bool
     */
    protected function isGet()
    {
        $method = $this->request()->getMethod();
        if ($method != 'GET') {
            return false;
        }
        return true;
    }

    /**
     * 是否PUT请求
     * @return bool
     */
    protected function isPut()
    {
        $method = $this->request()->getMethod();
        if ($method != 'PUT') {
            return false;
        }
        return true;
    }

    /**
     * 是否PATCH请求
     * @return bool
     */
    protected function isPatch()
    {
        $method = $this->request()->getMethod();
        if ($method != 'PATCH') {
            return false;
        }
        return true;
    }

    /**
     * 是否DELETE请求
     * @return bool
     */
    protected function isDelete()
    {
        $method = $this->request()->getMethod();
        if ($method != 'DELETE') {
            return false;
        }
        return true;
    }

    /**
     * @return bool
     */
    protected function isAjax(): bool
    {
        if (strtolower($this->request()->getHeaderLine('x-requested-with')) == 'xmlhttprequest') {
            return true;
        }
        return false;
    }
}
